home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / gfx / 3d / irit50src.lha / irit5 / irit / overload.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-14  |  33.6 KB  |  717 lines

  1. /*****************************************************************************
  2. *   "Irit" - the 3d (not only polygonal) solid modeller.             *
  3. *                                         *
  4. * Written by:  Gershon Elber                Ver 0.2, Mar. 1990   *
  5. ******************************************************************************
  6. *   Module to handle overloaded operators for the input parser module.         *
  7. * Note this module should be accessed by Input Parser only (InptPrsr.c).     *
  8. *****************************************************************************/
  9.  
  10. #include <stdio.h>
  11. #include <ctype.h>
  12. #include <math.h>
  13. #include <string.h>
  14. #include <signal.h>
  15. #include "program.h"
  16. #include "allocate.h"
  17. #include "attribut.h"
  18. #include "bool_lib.h"
  19. #include "freeform.h"
  20. #include "geomat3d.h"
  21. #include "inptprsg.h"
  22. #include "inptprsl.h"
  23. #include "objects.h"
  24. #include "overload.h"
  25.  
  26. /* The following table help to decide if the operand are legal for the given */
  27. /* operator. 5 entries for PLUS, MINUS, MULT, DIV, POWER. Each entry is a    */
  28. /* square matrix of number of object types by number of object types:         */
  29.  
  30. static IritExprType OverLoadDiadicTable[5][13][13] =
  31. /*    POLY_EXPR     NUMERIC_EXPR  POINT_EXPR   VECTOR_EXPR  PLANE_EXPR  MATRIX_EXPR  CURVE_EXPR  SURFACE_EXPR STRING_EXPR  OLST_EXPR    CTLPT_EXPR  TRIVAR_EXPR TRIMSRF_EXPR */
  32. { { /* PLUS */
  33.     { POLY_EXPR, NO_EXPR,      NO_EXPR,        NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    POLY_EXPR,   NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  34.     { NO_EXPR,     NUMERIC_EXPR, NO_EXPR,        NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     STRING_EXPR, NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  35.     { NO_EXPR,     NO_EXPR,      VECTOR_EXPR, VECTOR_EXPR, NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  36.     { NO_EXPR,     NO_EXPR,      VECTOR_EXPR, VECTOR_EXPR, NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  37.     { NO_EXPR,     NO_EXPR,      NO_EXPR,        NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  38.     { NO_EXPR,     NO_EXPR,      NO_EXPR,        NO_EXPR,     NO_EXPR,    MATRIX_EXPR, NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  39.     { NO_EXPR,     NO_EXPR,      NO_EXPR,        NO_EXPR,     NO_EXPR,    NO_EXPR,      CURVE_EXPR, NO_EXPR,     NO_EXPR,     NO_EXPR,     CURVE_EXPR, NO_EXPR,    NO_EXPR },
  40.     { POLY_EXPR, NO_EXPR,      NO_EXPR,        NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    POLY_EXPR,   NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  41.     { NO_EXPR,   STRING_EXPR,  NO_EXPR,        NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     STRING_EXPR, NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  42.     { NO_EXPR,   NO_EXPR,      NO_EXPR,        NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     OLST_EXPR,   NO_EXPR,    NO_EXPR,    NO_EXPR },
  43.     { NO_EXPR,   NO_EXPR,      NO_EXPR,        NO_EXPR,     NO_EXPR,    NO_EXPR,     CURVE_EXPR, NO_EXPR,     NO_EXPR,     NO_EXPR,     CURVE_EXPR, NO_EXPR,    NO_EXPR },
  44.     { NO_EXPR,   NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  45.     { NO_EXPR,   NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR } },
  46.  
  47.   { /* MINUS */
  48.     { POLY_EXPR, NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    POLY_EXPR,   NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  49.     { NO_EXPR,     NUMERIC_EXPR, NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  50.     { NO_EXPR,     NO_EXPR,      VECTOR_EXPR, VECTOR_EXPR, NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  51.     { NO_EXPR,     NO_EXPR,      VECTOR_EXPR, VECTOR_EXPR, NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  52.     { NO_EXPR,     NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  53.     { NO_EXPR,     NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    MATRIX_EXPR, NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  54.     { NO_EXPR,     NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  55.     { POLY_EXPR, NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    POLY_EXPR,   NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  56.     { NO_EXPR,   NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  57.     { NO_EXPR,   NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  58.     { NO_EXPR,   NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  59.     { NO_EXPR,   NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  60.     { NO_EXPR,   NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR } },
  61.  
  62.   { /* MULT */
  63.     { POLY_EXPR, NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    POLY_EXPR,   NO_EXPR,    POLY_EXPR,   NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  64.     { NO_EXPR,     NUMERIC_EXPR, POINT_EXPR,  VECTOR_EXPR, NO_EXPR,    MATRIX_EXPR, NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  65.     { NO_EXPR,     POINT_EXPR,   NUMERIC_EXPR,NUMERIC_EXPR,NO_EXPR,    POINT_EXPR,  NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  66.     { NO_EXPR,     VECTOR_EXPR,  NUMERIC_EXPR,NUMERIC_EXPR,NO_EXPR,    VECTOR_EXPR, NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  67.     { NO_EXPR,     NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  68.     { POLY_EXPR, MATRIX_EXPR,  POINT_EXPR,  VECTOR_EXPR, NO_EXPR,    MATRIX_EXPR, CURVE_EXPR, SURFACE_EXPR,NO_EXPR,     OLST_EXPR,   CTLPT_EXPR, TRIVAR_EXPR,TRIMSRF_EXPR },
  69.     { NO_EXPR,     NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    CURVE_EXPR,  NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  70.     { POLY_EXPR, NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    SURFACE_EXPR,NO_EXPR,    POLY_EXPR,   NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  71.     { NO_EXPR,   NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  72.     { NO_EXPR,   NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    OLST_EXPR,   NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  73.     { NO_EXPR,   NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    CTLPT_EXPR,  NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  74.     { NO_EXPR,   NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    TRIVAR_EXPR, NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  75.     { NO_EXPR,   NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    TRIMSRF_EXPR,NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR } },
  76.  
  77.   { /* DIV */
  78.     { POLY_EXPR, NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    POLY_EXPR,   NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  79.     { NO_EXPR,     NUMERIC_EXPR, NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  80.     { NO_EXPR,     NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  81.     { NO_EXPR,     NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  82.     { NO_EXPR,     NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  83.     { NO_EXPR,     NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  84.     { NO_EXPR,     NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  85.     { POLY_EXPR, NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    POLY_EXPR,   NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  86.     { NO_EXPR,   NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  87.     { NO_EXPR,   NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  88.     { NO_EXPR,   NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  89.     { NO_EXPR,   NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  90.     { NO_EXPR,   NO_EXPR,      NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR } },
  91.  
  92.   { /* POWER */
  93.     { POLY_EXPR, NO_EXPR,      NO_EXPR,        NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    POLY_EXPR,   NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  94.     { NO_EXPR,     NUMERIC_EXPR, NO_EXPR,        NO_EXPR,     NO_EXPR,    MATRIX_EXPR, NO_EXPR,    NO_EXPR,     STRING_EXPR, NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  95.     { NO_EXPR,     NO_EXPR,      VECTOR_EXPR, VECTOR_EXPR, NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  96.     { NO_EXPR,     NO_EXPR,      VECTOR_EXPR, VECTOR_EXPR, NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  97.     { NO_EXPR,     NO_EXPR,      NO_EXPR,        NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  98.     { NO_EXPR,     MATRIX_EXPR,  NO_EXPR,        NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  99.     { NO_EXPR,     NO_EXPR,      NO_EXPR,        NO_EXPR,     NO_EXPR,    NO_EXPR,      NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  100.     { POLY_EXPR, NO_EXPR,      NO_EXPR,        NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    POLY_EXPR,   NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  101.     { NO_EXPR,   STRING_EXPR,  NO_EXPR,        NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     STRING_EXPR, NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  102.     { NO_EXPR,   NO_EXPR,      NO_EXPR,        NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  103.     { NO_EXPR,   NO_EXPR,      NO_EXPR,        NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  104.     { NO_EXPR,   NO_EXPR,      NO_EXPR,        NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR },
  105.     { NO_EXPR,   NO_EXPR,      NO_EXPR,        NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,    NO_EXPR,     NO_EXPR,     NO_EXPR,     NO_EXPR,    NO_EXPR,    NO_EXPR } },
  106. };
  107.  
  108. /* The following table help to decide if the operand are legal for the given */
  109. /* operator. 1 entry for UNARMINUS. Each entry is a linear vector of length  */
  110. /* of number of object types:                             */
  111.  
  112. static IritExprType OverLoadMonadicTable[1][13] =
  113. /*  POLY_EXPR  NUMERIC_EXPR  POINT_EXPR  VECTOR_EXPR  PLANE_EXPR  MATRIX_EXPR  CURVE_EXPR  SURFACE_EXPR  STRING_EXPR  OLST_EXPR  CTLPT_EXPR TRIVAR_EXPR TRIMSRF_EXPR */
  114. { /* UNARMINUS */
  115.   { POLY_EXPR, NUMERIC_EXPR, POINT_EXPR, VECTOR_EXPR, PLANE_EXPR, MATRIX_EXPR, CURVE_EXPR, SURFACE_EXPR, NO_EXPR,     OLST_EXPR, NO_EXPR,   NO_EXPR,    NO_EXPR }
  116. };
  117.  
  118. static int OverLoadTypeCheckAux(int Operator,
  119.                 IritExprType Right,
  120.                 IritExprType Left,
  121.                 IritExprType *Result);
  122. static IPObjectStruct *ConvSrfToPolys(ParseTree *Srf);
  123.  
  124. /*****************************************************************************
  125. * DESCRIPTION:                                                               M
  126. * Performs type checking on the overloaded operators.                 M
  127. *   Returns TRUE if legal, and sets Result to returned object type.         M
  128. *   Allows multiple types (I.e. VECTOR_EXPR | MATRIX_EXPR is legal input).   M
  129. *   Note output Result may be multiple types as well is a such case.         M
  130. *                                                                            *
  131. * PARAMETERS:                                                                M
  132. *   Operator:     To apply to left and right operands.                       M
  133. *   Right, Left:  The two operands of the operations.                        M
  134. *   Result:       Type of the resulting operation.                           M
  135. *                                                                            *
  136. * RETURN VALUE:                                                              M
  137. *   int:          TRUE if operation is defined and legal, FALSE otherwise.   M
  138. *                                                                            *
  139. * KEYWORDS:                                                                  M
  140. *   OverLoadTypeCheck                                                        M
  141. *****************************************************************************/
  142. int OverLoadTypeCheck(int Operator,
  143.               IritExprType Right,
  144.               IritExprType Left,
  145.               IritExprType *Result)
  146. {
  147.     int i, j, NumRightTypes, NumLeftTypes;
  148.     IritExprType TmpResult;
  149.  
  150.     /* Compute how many types are feasible here (input). */
  151.     for (i = 1, NumRightTypes = 0; i < NO_EXPR; i <<= 1)
  152.     NumRightTypes += (i & Right) != 0;
  153.     for (i = 1, NumLeftTypes = 0; i < NO_EXPR; i <<= 1)
  154.     NumLeftTypes += (i & Left) != 0;
  155.  
  156.     if (NumLeftTypes == 0) {
  157.     if (Operator == UNARMINUS) {
  158.         *Result = 0;
  159.         for (i = 1; i < NO_EXPR; i <<= 1)
  160.         if ((i & Right) != 0)
  161.             if (OverLoadTypeCheckAux(Operator, (IritExprType) i, Left,
  162.                          &TmpResult))
  163.             *Result |= TmpResult;
  164.         return *Result != 0;
  165.     }
  166.     else
  167.         return FALSE;
  168.     }
  169.     if (NumLeftTypes < 1 || NumRightTypes < 1)
  170.     return FALSE;
  171.     else if (NumLeftTypes == 1 && NumRightTypes == 1)
  172.     return OverLoadTypeCheckAux(Operator, Right, Left, Result);
  173.     else {
  174.     /* More than one type in the input - compute union of the output     */
  175.         /* types and return the union.                         */
  176.     *Result = 0;
  177.         for (i = 1; i < NO_EXPR; i <<= 1)
  178.         if ((i & Right) != 0)
  179.         for (j = 1; j < NO_EXPR; j <<= 1)
  180.             if ((j & Left) != 0)
  181.             if (OverLoadTypeCheckAux(Operator,
  182.                          (IritExprType) i,
  183.                          (IritExprType) j,
  184.                          &TmpResult))
  185.                 *Result |= TmpResult;
  186.  
  187.     return *Result != 0;
  188.     }
  189. }
  190.  
  191. /*****************************************************************************
  192. * DESCRIPTION:                                                               *
  193. * Auxiliary function of OverLoadTypeCheck.                                   *
  194. *                                                                            *
  195. * PARAMETERS:                                                                *
  196. *   Operator:     To apply to left and right operands.                       *
  197. *   Right, Left:  The two operands of the operations.                        *
  198. *   Result:       Type of the resulting operation.                           *
  199. *                                                                            *
  200. * RETURN VALUE:                                                              *
  201. *   int:          TRUE if operation is defined and legal, FALSE otherwise.   *
  202. *****************************************************************************/
  203. static int OverLoadTypeCheckAux(int Operator,
  204.                 IritExprType Right,
  205.                 IritExprType Left,
  206.                 IritExprType *Result)
  207. {
  208.     int i, IRight, ILeft;
  209.  
  210.     for (i = 1, IRight = 0; i < Right; i <<= 1, IRight++);
  211.     for (i = 1, ILeft  = 0; i < Left;  i <<= 1, ILeft++);
  212.  
  213.     switch (Operator) {
  214.     case PLUS:
  215.     case MINUS:
  216.     case MULT:
  217.     case DIV:
  218.     case POWER:
  219.         *Result = OverLoadDiadicTable[Operator - OPERATORS_OFFSET]
  220.                      [IRight][ILeft];
  221.         return *Result != NO_EXPR;
  222.     case UNARMINUS:
  223.         *Result = OverLoadMonadicTable[0][IRight];
  224.         return *Result != NO_EXPR;
  225.     default:
  226.         IritFatalError("OverLoadTypeCheck: undefined operator");
  227.     }
  228.     return FALSE;                    /* Makes warning silent. */
  229. }
  230.  
  231. /*****************************************************************************
  232. * DESCRIPTION:                                                               M
  233. * Evaluates a monadic or diadic expression.                     M
  234. *   It is assumed the two operands are valid for the given expression - a    M
  235. * test which can be made using OverLoadTypeCheck routine (see above).         M
  236. *   Returns a pointer to a node with the result, NULL in case of error         M
  237. * (should not happen actually due to verification).                 M
  238. *                                                                            *
  239. * PARAMETERS:                                                                M
  240. *   Root:           The (overload) expression to evaluate.                   M
  241. *   TempR, TempL:   Two operands of the expression.                     M
  242. *   IError:         Error type if was one.                                   M
  243. *   CError:         Description of error if was one.                         M
  244. *                                                                            *
  245. * RETURN VALUE:                                                              M
  246. *   ParseTree *:    Reslut of evaluated tree.                                M
  247. *                                                                            *
  248. * KEYWORDS:                                                                  M
  249. *   OverLoadEvalOper                                                         M
  250. *****************************************************************************/
  251. ParseTree *OverLoadEvalOper(ParseTree *Root,
  252.                 ParseTree *TempR,
  253.                 ParseTree *TempL,
  254.                 InptPrsrEvalErrType *IError,
  255.                 char *CError)
  256. {
  257.     int i,
  258.     OperReversed = FALSE;
  259.     char *Str;
  260.     RealType R, *RL, *RR;
  261.     ParseTree *Temp,
  262.     *RetVal = Root;
  263.     IPObjectStruct *TempLObj, *TempRObj;
  264.  
  265.     switch (Root -> NodeKind) {              /* Dies if undefined operator. */
  266.     case PLUS:
  267.     case MINUS:
  268.     case MULT:
  269.     case DIV:
  270.     case POWER:
  271.         if (TempR == NULL ||
  272.         TempL == NULL ||
  273.         TempR -> PObj == NULL ||
  274.         TempL -> PObj == NULL)
  275.         return NULL;                       /* Error! */
  276.         break;
  277.  
  278.     case UNARMINUS:
  279.         if (TempR == NULL || TempR -> PObj == NULL)
  280.         return NULL;                       /* Error! */
  281.         break;
  282.  
  283.     default:
  284.         IritFatalError("OverLoadEvalOper: Undefined operator");
  285.     }
  286.  
  287.     /* Make TempL be bigger, so we need handle less cases. */
  288.     if (Root -> NodeKind != UNARMINUS &&
  289.     ((int) TempR -> PObj -> ObjType) > ((int) TempL -> PObj -> ObjType)) {
  290.     Temp = TempR;
  291.     TempR = TempL;
  292.     TempL = Temp;
  293.  
  294.     OperReversed = TRUE;
  295.     }
  296.  
  297.     switch (Root -> NodeKind) {
  298.     case PLUS:
  299.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
  300.         Root -> PObj = GenNUMValObject(TempL -> PObj -> U.R +
  301.                            TempR -> PObj -> U.R);
  302.         }
  303.         else if (IS_NUM_NODE(TempR) && IS_STR_NODE(TempL)) {
  304.         Root -> PObj = IPAllocObject("", IP_OBJ_STRING, NULL);
  305.         Str = Root -> PObj -> U.Str;
  306.         if (OperReversed) {
  307.             sprintf(Str, "%d", (int) (TempR -> PObj -> U.R));
  308.             strncpy(&Str[strlen(Str)],
  309.                 TempL -> PObj -> U.Str, LINE_LEN - 1);
  310.         }
  311.         else {
  312.             strncpy(Str, TempL -> PObj -> U.Str, LINE_LEN - 1);
  313.             sprintf(&Str[strlen(Str)], "%d",
  314.                 (int) (TempR -> PObj -> U.R));
  315.         }
  316.         }
  317.         else if (IS_PT_NODE(TempR) && IS_PT_NODE(TempL)) {
  318.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  319.         PT_ADD(Root -> PObj -> U.Vec,
  320.             TempL -> PObj -> U.Pt, TempR -> PObj -> U.Pt);
  321.         }
  322.         else if (IS_PT_NODE(TempR) && IS_VEC_NODE(TempL)) {
  323.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  324.         PT_ADD(Root -> PObj -> U.Vec,
  325.             TempL -> PObj -> U.Vec, TempR -> PObj -> U.Pt);
  326.         }
  327.         else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
  328.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  329.         PT_ADD(Root -> PObj -> U.Vec,
  330.             TempL -> PObj -> U.Vec, TempR -> PObj -> U.Vec);
  331.         }
  332.         else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
  333.         Root -> PObj = IPAllocObject("", IP_OBJ_MATRIX, NULL);
  334.                 MatAddTwo4by4(*Root -> PObj -> U.Mat,
  335.                   *TempL -> PObj -> U.Mat,
  336.                   *TempR -> PObj -> U.Mat);
  337.         }
  338.         else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
  339.              (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
  340.         TempLObj = ConvSrfToPolys(TempL);
  341.         TempRObj = ConvSrfToPolys(TempR);
  342.  
  343.         Root -> PObj = BooleanOR(TempLObj, TempRObj);
  344.         signal(SIGFPE, DefaultFPEHandler);  /* Default FPE trapping. */
  345.  
  346.         if (Root -> PObj == NULL) {
  347.             IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
  348.             UpdateCharError("Operator ", PLUS, Root);
  349.             RetVal = NULL;
  350.         }
  351.         }
  352.         else if (IS_STR_NODE(TempR) && IS_STR_NODE(TempL)) {
  353.         Root -> PObj = IPAllocObject("", IP_OBJ_STRING, NULL);
  354.         Str = Root -> PObj -> U.Str;
  355.         sprintf(Str, "%s%s", TempL -> PObj -> U.Str,
  356.                      TempR -> PObj -> U.Str);
  357.         }
  358.         else if (IS_OLST_NODE(TempR) && IS_OLST_NODE(TempL)) {
  359.             Root -> PObj = AppendLists(TempL -> PObj, TempR -> PObj);
  360.         }
  361.         else if ((IS_CTLPT_NODE(TempR) || IS_CRV_NODE(TempR)) &&
  362.              (IS_CTLPT_NODE(TempL) || IS_CRV_NODE(TempL))) {
  363.         if (OperReversed)
  364.             Root -> PObj = MergeCurvesAndCtlPoints(TempR -> PObj,
  365.                                TempL -> PObj);
  366.         else
  367.             Root -> PObj = MergeCurvesAndCtlPoints(TempL -> PObj,
  368.                                TempR -> PObj);
  369.         }
  370.         else
  371.         RetVal = NULL;
  372.         break;
  373.     case MINUS:
  374.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
  375.         Root -> PObj = GenNUMValObject(TempL -> PObj -> U.R -
  376.                            TempR -> PObj -> U.R);
  377.         }
  378.         else if (IS_PT_NODE(TempR) && IS_PT_NODE(TempL)) {
  379.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  380.         PT_SUB(Root -> PObj -> U.Vec,
  381.                TempL -> PObj -> U.Pt, TempR -> PObj -> U.Pt);
  382.         }
  383.         else if (IS_PT_NODE(TempR) && IS_VEC_NODE(TempL)) {
  384.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  385.         RL = OperReversed ? TempR -> PObj -> U.Pt
  386.                   : TempL -> PObj -> U.Vec;
  387.         RR = OperReversed ? TempL -> PObj -> U.Pt
  388.                   : TempR -> PObj -> U.Vec;
  389.         PT_SUB(Root -> PObj -> U.Vec, RL, RR);
  390.         }
  391.         else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
  392.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  393.         PT_SUB(Root -> PObj -> U.Vec,
  394.                TempL -> PObj -> U.Vec, TempR -> PObj -> U.Vec);
  395.         }
  396.         else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
  397.         Root -> PObj = IPAllocObject("", IP_OBJ_MATRIX, NULL);
  398.                 MatSubTwo4by4(*Root -> PObj -> U.Mat,
  399.                   *TempL -> PObj -> U.Mat,
  400.                   *TempR -> PObj -> U.Mat);
  401.         }
  402.         else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
  403.              (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
  404.         TempLObj = ConvSrfToPolys(TempL);
  405.         TempRObj = ConvSrfToPolys(TempR);
  406.  
  407.         Root -> PObj = BooleanSUB(TempLObj, TempRObj);
  408.         signal(SIGFPE, DefaultFPEHandler);  /* Default FPE trapping. */
  409.  
  410.         if (Root -> PObj == NULL) {
  411.             IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
  412.             UpdateCharError("Operator ", MINUS, Root);
  413.             RetVal = NULL;
  414.         }
  415.         }
  416.         else
  417.         RetVal = NULL;
  418.         break;
  419.     case MULT:
  420.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {
  421.         Root -> PObj = GenNUMValObject(TempL -> PObj -> U.R *
  422.                            TempR -> PObj -> U.R);
  423.         }
  424.         else if (IS_PT_NODE(TempR) && IS_PT_NODE(TempL)) {
  425.         Root -> PObj =
  426.             GenNUMValObject(DOT_PROD(TempL -> PObj -> U.Pt,
  427.                          TempR -> PObj -> U.Pt));
  428.         }
  429.         else if (IS_PT_NODE(TempR) && IS_VEC_NODE(TempL)) {
  430.         Root -> PObj =
  431.             GenNUMValObject(DOT_PROD(TempL -> PObj -> U.Vec,
  432.                          TempR -> PObj -> U.Pt));
  433.         }
  434.         else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
  435.         Root -> PObj =
  436.             GenNUMValObject(DOT_PROD(TempL -> PObj -> U.Vec,
  437.                          TempR -> PObj -> U.Vec));
  438.         }
  439.         else if (IS_MAT_NODE(TempR) && IS_MAT_NODE(TempL)) {
  440.         Root -> PObj = IPAllocObject("", IP_OBJ_MATRIX, NULL);
  441.                 MatMultTwo4by4(*Root -> PObj -> U.Mat,
  442.                    *TempL -> PObj -> U.Mat,
  443.                    *TempR -> PObj -> U.Mat);
  444.         }
  445.         else if (IS_NUM_NODE(TempR) && IS_PT_NODE(TempL)) {
  446.         Root -> PObj = IPAllocObject("", IP_OBJ_POINT, NULL);
  447.         PT_COPY(Root -> PObj -> U.Pt, TempL -> PObj -> U.Pt);
  448.         PT_SCALE(Root -> PObj -> U.Pt, TempR -> PObj -> U.R);
  449.         }
  450.         else if (IS_NUM_NODE(TempR) && IS_VEC_NODE(TempL)) {
  451.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  452.         PT_COPY(Root -> PObj -> U.Vec, TempL -> PObj -> U.Vec);
  453.         PT_SCALE(Root -> PObj -> U.Vec, TempR -> PObj -> U.R);
  454.         }
  455.         else if (IS_NUM_NODE(TempR) && IS_MAT_NODE(TempL)) {
  456.         Root -> PObj = IPAllocObject("", IP_OBJ_MATRIX, NULL);
  457.         MatScale4by4(*Root -> PObj -> U.Mat,
  458.                  *TempL -> PObj -> U.Mat,
  459.                  &TempR -> PObj -> U.R);
  460.         }
  461.         else if (IS_POLY_NODE(TempR) && IS_MAT_NODE(TempL)) {
  462.         Root -> PObj = GMTransformObject(TempR -> PObj,
  463.                          *TempL -> PObj -> U.Mat);
  464.         }
  465.         else if (IS_MAT_NODE(TempR) &&
  466.              (IS_CRV_NODE(TempL) ||
  467.               IS_SRF_NODE(TempL) ||
  468.               IS_CTLPT_NODE(TempL) ||
  469.               IS_OLST_NODE(TempL) ||
  470.               IS_TRIVAR_NODE(TempL) ||
  471.               IS_TRIMSRF_NODE(TempL))) {
  472.         Root -> PObj = GMTransformObject(TempL -> PObj,
  473.                          *TempR -> PObj -> U.Mat);
  474.         }
  475.         else if (IS_VEC_NODE(TempR) && IS_MAT_NODE(TempL)) {
  476.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  477.         MatMultVecby4by4(Root -> PObj -> U.Vec,
  478.                  TempR -> PObj -> U.Vec,
  479.                  *TempL -> PObj -> U.Mat);
  480.         }
  481.         else if (IS_PT_NODE(TempR) && IS_MAT_NODE(TempL)) {
  482.         Root -> PObj = IPAllocObject("", IP_OBJ_POINT, NULL);
  483.         MatMultVecby4by4(Root -> PObj -> U.Pt,
  484.                  TempR -> PObj -> U.Pt,
  485.                  *TempL -> PObj -> U.Mat);
  486.         }
  487.         else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
  488.              (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
  489.         TempLObj = ConvSrfToPolys(TempL);
  490.         TempRObj = ConvSrfToPolys(TempR);
  491.  
  492.         Root -> PObj = BooleanAND(TempLObj, TempRObj);
  493.         signal(SIGFPE, DefaultFPEHandler);  /* Default FPE trapping. */
  494.  
  495.         if (Root -> PObj == NULL) {
  496.             IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
  497.             UpdateCharError("Operator ", MULT, Root);
  498.             RetVal = NULL;
  499.         }
  500.         }
  501.         else
  502.         RetVal = NULL;
  503.         break;
  504.     case DIV:
  505.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {  /* Numeric div. */
  506.         if (TempR -> PObj -> U.R != 0.0) {
  507.             Root -> PObj = GenNUMValObject(TempL -> PObj -> U.R /
  508.                            TempR -> PObj -> U.R);
  509.         }
  510.         else {
  511.             *IError = IE_ERR_DIV_BY_ZERO;
  512.             strcpy(CError, "/");
  513.             RetVal = NULL;
  514.         }
  515.         }
  516.         else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
  517.              (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
  518.         TempLObj = ConvSrfToPolys(TempL);
  519.         TempRObj = ConvSrfToPolys(TempR);
  520.  
  521.         Root -> PObj = OperReversed ? BooleanCUT(TempRObj, TempLObj)
  522.                         : BooleanCUT(TempLObj, TempRObj);
  523.         signal(SIGFPE, DefaultFPEHandler);  /* Default FPE trapping. */
  524.  
  525.         if (Root -> PObj == NULL) {
  526.             IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
  527.             UpdateCharError("Operator ", DIV, Root);
  528.             RetVal = NULL;
  529.         }
  530.         }
  531.         else
  532.         RetVal = NULL;
  533.         break;
  534.     case POWER:
  535.         if (IS_NUM_NODE(TempR) && IS_NUM_NODE(TempL)) {/* Numeric power. */
  536.         Root -> PObj = GenNUMValObject(pow(TempL -> PObj -> U.R,
  537.                            TempR -> PObj -> U.R));
  538.         }
  539.         else if (IS_NUM_NODE(TempR) && IS_MAT_NODE(TempL)) {
  540.         /* Power MUST be integer in this case. */
  541.         i = (int) TempR -> PObj -> U.R;
  542.         if (!APX_EQ(i, TempR -> PObj -> U.R) || i < -1) {
  543.             *IError = IE_ERR_MAT_POWER;
  544.             strcpy(CError, "^");
  545.             RetVal = NULL;
  546.         }
  547.         Root -> PObj = IPAllocObject("", IP_OBJ_MATRIX, NULL);
  548.         if (i == -1) {             /* Generate the inverse matrix: */
  549.             if (!MatInverseMatrix(*TempL -> PObj -> U.Mat,
  550.                       *Root -> PObj -> U.Mat)) {
  551.             *IError = IE_ERR_MAT_POWER;
  552.             strcpy(CError, "^");
  553.             RetVal = NULL;
  554.             }
  555.         }
  556.         else {                  /* I must be positive integer. */
  557.             MatGenUnitMat(*Root -> PObj -> U.Mat);
  558.             while (i--)
  559.                 MatMultTwo4by4(*Root -> PObj -> U.Mat,
  560.                        *Root -> PObj -> U.Mat,
  561.                        *TempL -> PObj -> U.Mat);
  562.         }
  563.         }
  564.         else if (IS_NUM_NODE(TempR) && IS_STR_NODE(TempL)) {
  565.         Root -> PObj = IPAllocObject("", IP_OBJ_STRING, NULL);
  566.         Str = Root -> PObj -> U.Str;
  567.         if (OperReversed) {
  568.             sprintf(Str, GlblFloatFormat, TempR -> PObj -> U.R);
  569.             strcpy(&Str[strlen(Str)], TempL -> PObj -> U.Str);
  570.         }
  571.         else {
  572.             strcpy(Str, TempL -> PObj -> U.Str);
  573.             sprintf(&Str[strlen(Str)], GlblFloatFormat,
  574.                 TempR -> PObj -> U.R);
  575.         }
  576.         }
  577.         else if (IS_PT_NODE(TempR) && IS_PT_NODE(TempL)) {
  578.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  579.         GMVecCrossProd(Root -> PObj ->U.Vec,
  580.                    TempR -> PObj -> U.Pt,
  581.                    TempL -> PObj -> U.Pt);
  582.         }
  583.         else if (IS_PT_NODE(TempR) && IS_VEC_NODE(TempL)) {
  584.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  585.         GMVecCrossProd(Root -> PObj ->U.Vec,
  586.                    OperReversed ? TempL -> PObj -> U.Vec
  587.                         : TempR -> PObj -> U.Pt,
  588.                    OperReversed ? TempR -> PObj -> U.Pt
  589.                         : TempL -> PObj -> U.Vec);
  590.         }
  591.         else if (IS_VEC_NODE(TempR) && IS_VEC_NODE(TempL)) {
  592.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  593.         GMVecCrossProd(Root -> PObj ->U.Vec,
  594.                    TempR -> PObj -> U.Vec,
  595.                    TempL -> PObj -> U.Vec);
  596.         }
  597.         else if ((IS_POLY_NODE(TempR) || IS_SRF_NODE(TempR)) &&
  598.              (IS_POLY_NODE(TempL) || IS_SRF_NODE(TempL))) {
  599.         TempLObj = ConvSrfToPolys(TempL);
  600.         TempRObj = ConvSrfToPolys(TempR);
  601.  
  602.         Root -> PObj = BooleanMERGE(TempLObj, TempRObj);
  603.         signal(SIGFPE, DefaultFPEHandler);  /* Default FPE trapping. */
  604.  
  605.         if (Root -> PObj == NULL) {
  606.             IPGlblEvalError = IE_ERR_BOOLEAN_ERR;
  607.             UpdateCharError("Operator ", MINUS, Root);
  608.             RetVal = NULL;
  609.         }
  610.         }
  611.         else if (IS_STR_NODE(TempR) && IS_STR_NODE(TempL)) {
  612.         Root -> PObj = IPAllocObject("", IP_OBJ_STRING, NULL);
  613.         Str = Root -> PObj -> U.Str;
  614.         sprintf(Str, "%s%s", TempL -> PObj -> U.Str,
  615.                      TempR -> PObj -> U.Str);
  616.         }
  617.         else
  618.         RetVal = NULL;
  619.         break;
  620.     case UNARMINUS:
  621.         if (IS_NUM_NODE(TempR)) {
  622.         Root -> PObj = GenNUMValObject(-TempR -> PObj -> U.R);
  623.         }
  624.         else if (IS_PT_NODE(TempR)) {
  625.         Root -> PObj = IPAllocObject("", IP_OBJ_POINT, NULL);
  626.         PT_COPY(Root -> PObj -> U.Pt, TempR -> PObj -> U.Pt);
  627.         PT_SCALE(Root -> PObj -> U.Pt, -1.0);
  628.         }
  629.         else if (IS_VEC_NODE(TempR)) {
  630.         Root -> PObj = IPAllocObject("", IP_OBJ_VECTOR, NULL);
  631.         PT_COPY(Root -> PObj -> U.Vec, TempR -> PObj -> U.Vec);
  632.         PT_SCALE(Root -> PObj -> U.Vec, -1.0);
  633.         }
  634.         else if (IS_PLANE_NODE(TempR)) {
  635.         Root -> PObj = IPAllocObject("", IP_OBJ_PLANE, NULL);
  636.         PLANE_COPY(Root -> PObj -> U.Plane, TempR -> PObj -> U.Plane);
  637.         for (i = 0; i < 4; i++)
  638.             Root -> PObj -> U.Plane[i] = -Root -> PObj -> U.Plane[i];
  639.         }
  640.         else if (IS_MAT_NODE(TempR)) {
  641.         Root -> PObj = IPAllocObject("", IP_OBJ_MATRIX, NULL);
  642.         R = -1.0;
  643.         MatScale4by4(*Root -> PObj -> U.Mat,
  644.                  *TempR -> PObj -> U.Mat,
  645.                  &R);
  646.         }
  647.         else if (IS_POLY_NODE(TempR)) {
  648.         Root -> PObj = BooleanNEG(TempR -> PObj);
  649.         signal(SIGFPE, DefaultFPEHandler);  /* Default FPE trapping. */
  650.         }
  651.         else if (IS_CRV_NODE(TempR)) {
  652.         Root -> PObj = CurveReverse(TempR -> PObj);
  653.         }
  654.         else if (IS_SRF_NODE(TempR)) {
  655.         Root -> PObj = SurfaceReverse(TempR -> PObj);
  656.         }
  657.         else if (IS_OLST_NODE(TempR)) {
  658.         Root -> PObj = ReverseListObj(TempR -> PObj);
  659.         }
  660.         else
  661.         RetVal = NULL;
  662.         break;
  663.     }
  664.     if (RetVal == NULL && *IError == IPE_NO_ERR) { /* Put general error msg: */
  665.     *IError = IE_ERR_TYPE_MISMATCH;
  666.     switch (Root -> NodeKind) {
  667.         case PLUS:
  668.         strcpy(CError, "Operator +");
  669.         break;
  670.         case MINUS:
  671.         strcpy(CError, "Operator -");
  672.         break;
  673.         case MULT:
  674.         strcpy(CError, "Operator *");
  675.         break;
  676.         case DIV:
  677.         strcpy(CError, "Operator /");
  678.         break;
  679.         case POWER:
  680.         strcpy(CError, "Operator ^");
  681.         break;
  682.         case UNARMINUS:
  683.         strcpy(CError, "Operator (unary) -");
  684.         break;
  685.     }
  686.     }
  687.  
  688.     return RetVal;
  689. }
  690.  
  691. /*****************************************************************************
  692. * DESCRIPTION:                                                               *
  693. * If given object is a surface, its polygonal representation object is       *
  694. * returned instead. Otherwise the given pointer is returned as is.           *
  695. *                                                                            *
  696. * PARAMETERS:                                                                *
  697. *   Srf:       To convert to polygons and return a polygonal approximation.  *
  698. *                                                                            *
  699. * RETURN VALUE:                                                              *
  700. *   IPObjectStruct *:  A polygona approximation of Srf, or original object   *
  701. *                      if not a surface.                                     *
  702. *****************************************************************************/
  703. static IPObjectStruct *ConvSrfToPolys(ParseTree *Srf)
  704. {
  705.     IPObjectStruct *PObjPolys;
  706.     if (!IS_SRF_NODE(Srf))
  707.     return Srf -> PObj;
  708.  
  709.     if ((PObjPolys = AttrGetObjectObjAttrib(Srf -> PObj, "_polygons"))
  710.                                 == NULL) {
  711.         ComputeSurfacePolygons(Srf -> PObj);
  712.         PObjPolys = AttrGetObjectObjAttrib(Srf -> PObj, "_polygons");
  713.     }
  714.  
  715.     return PObjPolys;
  716. }
  717.